package com.yindian.cos.logging.elastic;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.nosql.appender.NoSqlProvider;
import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;

/**
 * 解析自定义Elasticsearch标签，并生成es客户端
 *
 * @author zhangchuanhao
 * @create 2018/11/1
 */
@Plugin(name = "Elasticsearch", category = "Core", printObject = true)
public class ElasticsearchProvider implements NoSqlProvider<ElasticsearchConnection> {

    private final String host;
    private final int port;
    private final String index;
    private final String type;
    private final int maxActionsPerBulkRequest;
    private final int maxConcurrentBulkRequests;
    private final ByteSizeValue maxVolumePerBulkRequest;
    private final TimeValue flushInterval;
    private final String packageName;

    public ElasticsearchProvider(String host,
                                 int port,
                                 String index,
                                 String type,
                                 int maxActionsPerBulkRequest,
                                 int maxConcurrentBulkRequests,
                                 ByteSizeValue maxVolumePerBulkRequest,
                                 TimeValue flushInterval,
                                 String packageName) {
        this.host = host;
        this.port = port;
        this.index = index;
        this.type = type;
        this.maxActionsPerBulkRequest = maxActionsPerBulkRequest;
        this.maxConcurrentBulkRequests = maxConcurrentBulkRequests;
        this.maxVolumePerBulkRequest = maxVolumePerBulkRequest;
        this.flushInterval = flushInterval;
        this.packageName = packageName;
    }


    @Override
    public ElasticsearchConnection getConnection() {
        return ElasticsearchConnectionPool.getElasticsearchConnection(host,
                port,
                index,
                type,
                maxActionsPerBulkRequest,
                maxConcurrentBulkRequests,
                maxVolumePerBulkRequest,
                flushInterval,
                packageName);
    }

    @PluginFactory
    public static ElasticsearchProvider createNoSqlProvider(
            @PluginAttribute("host") String host,
            @PluginAttribute("port") String port,
            @PluginAttribute("index") String index,
            @PluginAttribute("type") String type,
            @PluginAttribute("maxActionsPerBulkRequest") String maxActionsPerBulkRequest,
            @PluginAttribute("maxConcurrentBulkRequests") String maxConcurrentBulkRequests,
            @PluginAttribute("maxVolumePerBulkRequest") String maxVolumePerBulkRequest,
            @PluginAttribute("flushInterval") String flushInterval,
            @PluginAttribute("packageName") String packageName) {
        if (host == null || host.isEmpty()) {
            host = "localhost";
        }
        if (StringUtils.isBlank(port)) {
            port = "9200";
        }
        if (index == null || index.isEmpty()) {
            index = "'log4j2-es-'yyyyMMdd";
        }
        if (type == null || type.isEmpty()) {
            type = "log4j2-es";
        }
        if (StringUtils.isBlank(maxActionsPerBulkRequest)) {
            maxActionsPerBulkRequest = "1000";
        }
        if (StringUtils.isBlank(maxConcurrentBulkRequests)) {
            maxConcurrentBulkRequests = 2 * Runtime.getRuntime().availableProcessors() + "";
        }
        if (StringUtils.isBlank(maxVolumePerBulkRequest)) {
            maxVolumePerBulkRequest = "10";
        }
        if (StringUtils.isBlank(flushInterval)) {
            flushInterval = "5";
        }
        return new ElasticsearchProvider(host,
                Integer.valueOf(port),
                index,
                type,
                Integer.valueOf(maxActionsPerBulkRequest),
                Integer.valueOf(maxConcurrentBulkRequests),
                new ByteSizeValue(Long.valueOf(maxVolumePerBulkRequest), ByteSizeUnit.MB),
                TimeValue.timeValueSeconds(Long.valueOf(flushInterval)),
                packageName
        );
    }

}
